(function($) {
    $.fn.validador = function (options) {
	var events = ['keyup'];
	if (options && options.events) {
	    events = options.events;
	    delete(options.events);
	}
	settings = $.extend({}, { 
	    icon: 'ui-icon-alert',
	    delay: 500,
	    hideTimeout: 1500
	}, options);
	this.data('vSettings', settings);
	for (i in events) {
	    $('tr:visible .scfValidate span[idValidar]', this).each (function (n, el) {
		var span = $(el);
		span.data('vSettings', settings);
		$('#'+span.attr('idValidar')).bind(events[i], function (e) {
		    var ui = $(e.target);
		    clearTimeout (ui.data('timeout'));
		    ui.data('timeout', setTimeout("$('#"+e.target.id+"').validar()", settings.delay));
		});
	    });
	}
    };
    $.fn.validar = function () {
	var aValidar = $('tr:visible .scfValidate span[idValidar]', this);
	if (aValidar.length) {
	    var valido = true;
	    aValidar.each(function(i, j) {
		valido = $('#'+$(j).attr('idValidar')).validar() && valido;
	    });
	    return valido;
	}
	var ok = true;
	var par = this.parents('tr');
	$('.mensajeError', par).remove();
	var validator = $('.scfValidate span[idvalidar]', par);
	var attrs = validator.get(0).attributes;
	var value = jQuery.trim(this.val());
	var l = attrs.length;
	dance:
	for (i=0; i < l; i++) {
	    switch (attrs[i].name) {
		case 'style':
		case 'idvalidar':
		    continue;
		case 'if_empty':
		    if (value!='') { ok = true; break dance; } break;
		case 'if_full':
		    if (value=='') { ok = true; break dance; } break;
		case 'required':
		    if (attrs[i].value=='true' && value=='') { ok = false; } break;
		case 'maxlength':
		    if (value.length > attrs[i].value) { ok = false; } break;
		case 'minlength':
		    if (value.length < attrs[i].value) { ok = false; } break;
		case 'mask':
		    var pattern = attrs[i].value;
		    if ($.patterns[pattern]==undefined) {
			try {
			    pattern = new RegExp(pattern);
			} catch (e) {
			    pattern = undefined;
			}
		    } else
			pattern = this.patterns[pattern];
		    if (verify.pattern != undefined) {
			if (value.match(verify.pattern) == null) ok = false;
		    } else
			alert ("Error: '" + attrs[i].value + "' mask do not exists");
		break;
		case 'compare' :
		    var compare = attrs[i].value;
		    var operation = compare.substr(0,2);
		    compare = compare.substr(3)
		    if (compare.substr(0,1)=='#')
			compare = $(compare).val();
		    if (compare.substr(0,1) != '@')
			compare = "'"+compare+"'";
		    else
			compare = parseInt(compare, 10);
		    eval('compare = (value '+ $.operators[operation] +' compare);');
		    if (!compare) ok = false;
		break;
	    }
	}
	if (!ok) 
	    this.emitirError();
	return ok;
    };
    $.fn.emitirError = function () {
	var par = this.parents('tr');
	var validator = $('.scfValidate span[idvalidar]', par);
	var settings = validator.data('vSettings') || {};
	var div = $('<div class="mensajeError ui-widget">'+
	    '<div class="ui-state-error ui-corner-all" style="padding: 0pt 0.7em;"><p>'+
	    '<span class="ui-icon '+settings.icon+'" style="float:left;margin-right: 0.3em;"></span>'+
	    '<strong>Error: </strong>'+validator.html()+'</p></div></div>');
	par.append(div);
	if (settings.hideTimeout > 0)
	    div.delay(settings.hideTimeout).fadeOut('slow', function () {
		$(this).remove(); });
	return false;
    };
    $.patterns = {
	alphabetic: /^[^0-9]*$/gi,
	born: /^[0-9]{2}\/[0-9]{2}\/(19)[0-9]{2}$/gi,
	cuit: /^[0-9]{2}\-[0-9]{8}\-[0-9]{1}$/gi,
	date: /^[0-9]{2}\/[0-9]{2}\/[0-9]{4}$/gi,
	email: /\b[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b/gi,
	ip: /^((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})$/gi,
	mac: /^(([A-F]|[0-9]|[a-f]){2}\:){5}([A-F]|[0-9]|[a-f]){2}$/gi,
	money: /^[0-9]+(\,[0-9]{2})*$/gi,
	numeric: /^[0-9]*$/gi,
	zip: /^[0-9]{5}\-[0-9]{4}$/gi
    };
    $.operators = {
	eq: '==',
	ne: '!=',
	gt: '>',
	lt: '<',
	ge: '>=',
	le: '<='
    }
})(jQuery);